﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using AgnisEbmtTranslator;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Xml;
using AgnisDAL;
using AgnisDAL.AGNIS_FORMSDataSetTableAdapters;

namespace TestApplication
{
    class MyTranslatorThreadHandle
    {
        FormTest  m_form;
        private BindingSource _bindingSource;
        private Boolean storeToDB;        
        private int nTransplants;
        private int paperFormNumber;
        private int formPublicId;
        private volatile int steps;
        private String currentEbmtDbConnectionString;
        private String currentMappingInfoConnectionString;
        private String currentAgnisStagingConnectionString;
        AgnisDAL.ServiceAgnis.FormRevision myGeneratedFormRevision;
        AgnisDAL.ServiceAgnis.FormRevision myFake2400FormRevision;
        static QueriesTableAdapter qAdapter = new QueriesTableAdapter();
        private int selectedIndex;
        // Main thread sets this event to stop worker thread:
        ManualResetEvent m_EventStop;
        // Worker thread sets this event when it is stopped:
        ManualResetEvent m_EventStopped;
        private string version = "1.0";  //RRA
        private int visit_id = -2;

        public MyTranslatorThreadHandle(BindingSource bs, FormTest mainForm, ManualResetEvent eventStop, ManualResetEvent eventStopped)
        {
            _bindingSource = bs;
            m_form = mainForm;
            m_EventStop = eventStop;
            m_EventStopped = eventStopped;
        }
        
        public BindingSource CurrentBindingSource
        {
            get { return _bindingSource; }
            set { _bindingSource = value; }
        }

        public  int ThreadSteps
        {
            get { return steps; }
            set { steps = value; }
        }

        public FormTest MainForm
        {
            get { return m_form; }
            set { m_form = value; }
        }

        public Boolean StoreToDataBase
        {
            get { return storeToDB; }
            set { storeToDB = value; }
        }

        

        public int NumberOfTransplantsToProcess
        {
            get { return nTransplants ; }
            set { nTransplants = value; }
        }

        public int AgnisPaperFormNumber
        {
            get { return paperFormNumber ; }
            set { paperFormNumber  = value; }
        }


        public int SelectedIndex
        {
            get { return selectedIndex; }
            set { selectedIndex = value; }
        }

        public void SetCurrentEbmtDbConnectionString(String cString)
        {
            currentEbmtDbConnectionString = cString;
        }

        public void SetCurrentMappingInfoConnectionString(String cString)
        {
            currentMappingInfoConnectionString = cString;
        }

        public void SetCurrentAgnisStagingConnectionString(String cString)
        {
            currentAgnisStagingConnectionString = cString;
        }

        private void SetFormPublicId(int _paperFormNumber)
        {
            switch (_paperFormNumber)
            {
                case 2400:
                    formPublicId = 3002012;
                    version = "2.0";
                    break;
                case 2450:
                    formPublicId = 2898108;
                    visit_id = -1; // 100 days
                    break;
                case 2900:
                    formPublicId = 2892254;
                    break;
                default:
                    break;
            }
        }
        public void ExecuteTranslationProcess()
        {
            if (_bindingSource.Count > nTransplants)
            {
                TranslatorProcess tProcess = new TranslatorProcess(currentEbmtDbConnectionString, currentMappingInfoConnectionString);
                    for (int i = 0; i < nTransplants; i++)
                    {
                        DataRowView dView;
                        if (nTransplants==1 && selectedIndex >= 0 && selectedIndex < _bindingSource.Count)
                        {
                            dView = (DataRowView)_bindingSource[selectedIndex];
                        }
                        else
                        {
                            dView = (DataRowView)_bindingSource[i];
                        }
                        int id = (int)dView["ID"];
                        int idaa = (int)dView["IDAA"];
                        int vIBMTRId;
                        if (!int.TryParse(dView["CRID"].ToString(), out vIBMTRId))
                        { throw new Exception("CRID not valid."); }
                        DateTime dateOfTransplant = (DateTime)dView["IDAABC"];
                        Object[] parameters = new Object[] { id, idaa, dateOfTransplant, (bool)true };
                        m_form.Invoke(m_form.m_DelegateRefreshStatus, new Object[] { parameters });
                        AgnisDAL.ServiceAgnis.FormRevision myTempGeneratedFormRevision;


                        SetFormPublicId(paperFormNumber);
                        //RRA                        
                        //check if Form has already been sent, then get the instance_ID
                        AgnisDAL.AGNIS_FORMSDataSet dsAgnisForms = new AGNIS_FORMSDataSet();
                        AgnisDAL.cAgnisDAL.SetConnectionString(currentAgnisStagingConnectionString);
                        AgnisDAL.cAgnisDAL.LoadAgnisStagingDb(dsAgnisForms);
                        string instance_Id = "";
                        if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(visit_id,id, idaa, paperFormNumber) != null)
                        {                            
                            int formRevision_id,outputFormRevision_id, form_Id;
                            formRevision_id = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(visit_id, id, idaa, paperFormNumber).FORM_REVISION_ID;
                            outputFormRevision_id = (int)qAdapter.GetOutput_FR_id(formRevision_id);
                            form_Id = (int)dsAgnisForms.FORM_REVISION.FindByFORM_REVISION_ID(outputFormRevision_id).FORM_ID;
                            instance_Id = dsAgnisForms.FORM.FindByFORM_ID(form_Id).INSTANCE_ID;   
                        }
                        myTempGeneratedFormRevision = tProcess.GenerateAgnisFormForPatient(id, idaa, 
                            dateOfTransplant, paperFormNumber, formPublicId, 
                            decimal.Parse(version, System.Globalization.CultureInfo.CreateSpecificCulture("en-US")), 
                            TranslatorProcess.AgnisForm2450DuePeriods.HundredDays,
                            instance_Id);
                        myGeneratedFormRevision=myTempGeneratedFormRevision;
                        steps = i;
                        if (storeToDB)
                        {                           
                            AgnisDAL.cAgnisDAL.SendFormRevisionToDB(myTempGeneratedFormRevision, paperFormNumber, formPublicId,visit_id,id,idaa,dateOfTransplant);
                        }
                        // Make synchronous call to main form.
                        // MainForm.RefreshStatus function runs in main thread.
                        Object[] parametersEnd = new Object[] { id, idaa, dateOfTransplant, (bool)false };
                        m_form.Invoke(m_form.m_DelegateRefreshStatus, new Object[] { parametersEnd });

                        // check if thread is cancelled
                        if (m_EventStop.WaitOne(0, true))
                        { 
                            // clean-up operations may be placed here
                            // ...

                            // inform main thread that this thread stopped
                            m_EventStopped.Set();

                            return;
                        }
                }
            }
            // Make synchronous call to main form
            // to inform it that thread finished
            Object[] parametersWhenFinished = new Object[] { myGeneratedFormRevision,myFake2400FormRevision };
            m_form.Invoke(m_form.m_DelegateThreadFinished, new Object[] {parametersWhenFinished});
        }

        private AgnisDAL.ServiceAgnis.FormRevision LoadFake2400FormObject(int cRID, DateTime dateOfTransplant)
        {
            //Read a xml file corresponding to form 2400.
            System.IO.FileStream fs =
             System.IO.File.OpenRead(@"D:\Mes documents\Agnis Translator Output\2400r2v2-skel-EBMT.xml");
            System.IO.StreamReader sr = new System.IO.StreamReader(fs);
            string data = sr.ReadToEnd();

            data = data.Replace("${#TestSuite#CRID}", cRID.ToString());
            data = data.Replace("${#TestSuite#DATE}", dateOfTransplant.ToShortDateString());
            

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(data);
            //Serialize the file data using the FormRevision data type.
            XmlSerializer s = new XmlSerializer(typeof(AgnisDAL.ServiceAgnis.FormRevision));
            string xmlString = doc.OuterXml.ToString();
            byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlString);
            MemoryStream ms = new MemoryStream(buffer);
            XmlReader reader = new XmlTextReader(ms);
            Exception caught = null;

            try
            {
                object o = s.Deserialize(reader);
              AgnisDAL.ServiceAgnis.FormRevision fInput = (AgnisDAL.ServiceAgnis.FormRevision)o;
              return fInput;
            }
            catch (Exception ex)
            {
                caught = ex;
            }
            finally
            {
                reader.Close();
            }
            return null;
        }

    }
}
